﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Windows.ApplicationModel.AppService;
using Windows.Foundation.Collections;
using Xiaowei.Diagnostics;
using Xiaowei.Settings;

namespace Xiaowei.Services
{
    public enum HotkeyId
    {
        Wakeup = 1001,
        OpenLocalFolder = 1002,
        ToggleSdkLog = 1003,
        ToggleTestPanel = 1004,
    }

    public enum Modifiers
    {
        Alt = 1,
        Control = 2,
        Shift = 4,
        Windows = 8,
        NoRepeat = 16384
    }




    public class HotkeyService
    {
        public class HotkeyArgs : IEquatable<HotkeyArgs>
        {

            public Modifiers FsModifiers { get; set; }
            public string Key { get; set; }
            public Action Action { get; set; }
            public HotkeyRegisterResult RegisterResult { get; set; }
            public bool Equals(HotkeyArgs other)
            {
                return other.Action == Action
                    && other.FsModifiers == FsModifiers
                    && other.Key == Key;
            }

            public override int GetHashCode()
            {
                return base.GetHashCode();
            }

            public static bool operator ==(HotkeyArgs left, HotkeyArgs right)
            {
                return left.Equals(right);
            }

            public static bool operator !=(HotkeyArgs left, HotkeyArgs right)
            {
                return !(left == right);
            }

            public override bool Equals(object obj)
            {
                return obj is HotkeyArgs && Equals((HotkeyArgs)obj);
            }
        }
        public enum HotkeyRegisterResult
        {
            OK=1,
            Error=2,
            Conflict=3,
        }
        Dictionary<int, HotkeyArgs> HotkeyDictionary;
        public delegate void HotKeyEventHandler();

        private static readonly Lazy<HotkeyService> LazyInstance = new Lazy<HotkeyService>(() =>
        {
            return new HotkeyService();
        }, LazyThreadSafetyMode.ExecutionAndPublication);
        public static HotkeyService Instance => LazyInstance.Value;
        private object HotkeyDictionaryLocker = new object();
        private HotkeyService()
        {
            HotkeyDictionary = new Dictionary<int, HotkeyArgs>();
        }
        private bool inited = false;
        public void Init()
        {
            if (inited) return;
            inited = true;
            ServiceFactory.NativeMessageService.HotkeyPressed+=(hotkey) => {
                Debug.WriteLine($"HotkeyPressed, {hotkey}");
                lock (HotkeyDictionaryLocker)
                {
                    if (HotkeyDictionary.ContainsKey(hotkey))
                    {
                        HotkeyDictionary[hotkey].Action();
                        Debug.WriteLine("Found hotkey in dictionary,and will invoke it.");
                    }
                    else
                    {
                        Debug.WriteLine("Not found hotkey in dictionary,please check it.");
                    }
                }

            };
        }

        public async Task<HotkeyRegisterResult> RegisterHotkeyAsync(int id, HotkeyArgs args)
        {
            if (string.IsNullOrEmpty(args.Key) || args.Key.Length != 1) return HotkeyRegisterResult.Error;
            //what ever the result of Register function, hotkey would be restore in a dictionary to wait next time the background service restart.
            lock (HotkeyDictionaryLocker)
            {
                args.RegisterResult = HotkeyRegisterResult.Error;
                HotkeyDictionary[id] = args;
            }
            HotkeyRegisterResult result = await RegisterHotkeyInnerAsync(id, args).ConfigureAwait(false);
            if (result == HotkeyRegisterResult.OK)
            {
                Debug.WriteLine("Register hotkey ok.");
            }
            else if (result == HotkeyRegisterResult.Conflict)
            {
                Debug.WriteLine("Register hotkey conflict. will retry when appservice restart.");
            }
            else
            {
                Debug.WriteLine("Register hotkey error. will retry when appservice restart.");
            }
            return result;
           
        }

        public HotkeyRegisterResult GetHotkeyState(int id)
        {
            lock (HotkeyDictionaryLocker)
            {
                if(HotkeyDictionary.ContainsKey(id))
                {
                    var args = HotkeyDictionary[id];
                    return args.RegisterResult;
                }
                else
                {
                    return HotkeyRegisterResult.Error;
                }
            }
        }

        private async Task<HotkeyRegisterResult> RegisterHotkeyInnerAsync(int id, HotkeyArgs args)
        {
            Debug.WriteLine($"RegisterHotkeyAsync, id:{id}, Modifiers:{args.FsModifiers}, key:{args.Key}");
            ValueSet v = new ValueSet()
            {
                { "Request", "RegisterHotkey" },
                { "Id", (int)id},
                { "Modifiers", (int)args.FsModifiers},
                { "Key", args.Key}
            };
            var ok = ServiceFactory.NativeMessageService.RegisterHotKey(id, args.FsModifiers, (Keys)args.Key[0]);
            Debug.WriteLine($"RegisterHotkeyAsync, ok:{ok}, id:{id}, Modifiers:{args.FsModifiers}, key:{args.Key}");
            if (ok)
            {
                args.RegisterResult = HotkeyRegisterResult.OK;
            }
            else
            {
                args.RegisterResult = HotkeyRegisterResult.Conflict;
            }
            return args.RegisterResult;
        }
    }
}
